package wsi.exp.exp3;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.rygh.core.util.counter.SimpleCounter;
import org.rygh.core.xml.XmlLeaf;
import org.rygh.core.xml.XmlObject;
import org.rygh.core.xml.XmlParser;
import org.rygh.core.xml.XmlPath;
import org.rygh.core.xml.XmlTree;
import org.rygh.semantic.model.ex.PredicatePath;

import wsi.exp.ExpXml.Tag;
import wsi.resolve.FactItem;

public class PathMatch {

	protected final Set<String> predicatePathSet = new HashSet<>();
	protected final List<PathMatchPair> pairs = new ArrayList<>();
	protected String content;

	public PathMatch() {

	}

	public PathMatch(XmlPath rootPath, SimpleCounter<String> factItemCounter) {
		load(rootPath, factItemCounter);
	}

	public void add(PathMatchPair pair) {
		pairs.add(pair);
		predicatePathSet.add(pair.getPredicatePath().getKey());
	}

	public boolean equalsTo(PathMatch o) {
		for (PathMatchPair i : pairs)
			if (o.find(i) == null)
				return false;

		return true;
	}

	public PathMatchPair find(PathMatchPair pair) {
		for (PathMatchPair p : pairs)
			if (pair.equalsTo(p))
				return p;

		return null;
	}

	public String getContent() {
		return content;
	}

	public List<PathMatchPair> getPairs() {
		return pairs;
	}

	@Deprecated
	public void load(String content) {
		this.content = content;

		String[] lines = content.split("\r\n");

		PredicatePath path = null;
		XmlPath xpath = null;
		PathMatchPair pair;

		for (int i = 0; i < lines.length; i++) {
			String line = lines[i].trim();

			if (line.isEmpty() || line.startsWith("// "))
				continue;

			String[] vals = line.split(",");
			assert vals.length == 4 : line;
			String[] nums = vals[1].trim().split("/");

			path = new PredicatePath(vals[2].trim());
			xpath = new XmlPath(vals[3].trim());

			pair = new PathMatchPair(path, xpath);
			pair.setConfidence(Double.parseDouble(vals[0]));
			pair.setCount(Integer.parseInt(nums[0]));
			pair.setTotal(Integer.parseInt(nums[1]));

			add(pair);
		}
	}

	public void load(XmlPath rootPath, SimpleCounter<String> factItemCounter) {
		PathMatchPair pair;

		for (String key : factItemCounter.keySet()) {
			FactItem item = (FactItem) factItemCounter.getValue(key);
			PredicatePath path = item.getCenterToValulePath();
			XmlPath xpath = item.getXmlLeaf().getXpath();
			XmlPath relpath = xpath.getRelativePathsTo(rootPath);

			if (relpath == null)
				relpath = xpath;

			pair = new PathMatchPair(path, relpath);
			pair.setCount(factItemCounter.get(key));
			pair.setTotal(factItemCounter.getNormalizeFactor());
			pair.setConfidence(item.getPercentage());

			add(pair);
		}
	}

	public void loadXml(String content) {
		this.content = content;

		XmlParser parser = new XmlParser(content);
		XmlTree xmltree = parser.parse();

		PredicatePath path = null;
		XmlPath xpath = null;
		PathMatchPair pair;

		List<XmlLeaf> nodes = xmltree.getNodesByXPath(XmlPath.compose(
				Tag.result, Tag.matches, Tag.match));

		for (XmlLeaf node : nodes) {
			XmlObject obj = node.getValue();

			path = new PredicatePath(node
					.getChildByName(Tag.predicate_path.name()).getValue()
					.getValue());
			xpath = new XmlPath(node.getChildByName(Tag.xpath.name())
					.getValue().getValue());

			pair = new PathMatchPair(path, xpath);
			pair.setConfidence(Double.parseDouble(node
					.getChildByName(Tag.percentage.name()).getValue()
					.getValue()));
			pair.setCount(Integer.parseInt(obj.getAttribute(Tag.count)));
			pair.setTotal(Integer.parseInt(obj.getAttribute(Tag.total)));

			add(pair);
		}
	}

	public int size() {
		return pairs.size();
	}
}
